package com.foundationmade.newbiz.core.security.service;

import java.util.ArrayList;
import java.util.Collection;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.foundationmade.newbiz.core.security.domain.SecurityIdentity;

/**
 * 사용자 인증을 위해 {@link org.springframework.security.core.userdetails.UserDetailsService} 인터페이스를 구현한다.
 * @author Devcken
 */
@Service("userDetailsService")
public class UserDetailsServiceImplement implements UserDetailsService
{
	private final static Logger logger = LoggerFactory.getLogger(UserDetailsServiceImplement.class);
	
	/**
	 * 보안 계정 관련 DAO를 주입받는다.
	 */
	@Resource(name="securityService")
	private SecurityService _securityService;
	
	/**
	 * 주어진 사용자 이름(보안 아이디)에 대한 사용자 정보(보안 계정 정보)를 로드한다.
	 * @param username 로드하려는 사용자 정보의 사용자 이름이 전달된다.
	 * @return 주어진 사용자 이름에 대한 사용자 정보가 반환된다.
	 */
	@Transactional
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException
	{
		try
		{
			SecurityIdentity identity = this._securityService.getSecurityIdentity(username);
			
			if (identity != null)
			{
				return toUserDetails(identity);
			}
		}
		catch (Exception error)
		{
			logger.error(error.getMessage(), error);
		}
		
		return null;
	}
	
	/**
	 * 보안 계정 정보를 사용자 정보로 변환한다.
	 * @param identity 변환하려는 보안 계정 정보를 설정한다.
	 * @return 주어진 보안 계정 정보가 사용자 정보로 변환되어 반환된다.
	 */
	private UserDetails toUserDetails(SecurityIdentity identity)
	{
		Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
		
		String authorityKey = identity.getAuthorityKey();
		
		SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority(authorityKey);
		
		authorities.add(grantedAuthority);
		
		return new User(identity.getSecurityId(), identity.getSecurityPassword(),
						identity.isEnabled(), !identity.isExpired(),
						!identity.isCredentialExpired(), !identity.isLocked(), authorities);
	}
}